channel-memory: async LLM digest worker with cost caps - #272
Conversation
Adds an off-hot-path background worker to the channel-memory adapter that compresses verbose raw_excerpt windows into sparse topic_rollup / sequence_rollup blocks via an LLM. /digest stays LLM-free — it only reads already-generated blocks. The worker is conservative: only raw_excerpt windows are summarized (hard events, tombstones, telemetry keep their faithful deterministic blocks); results must be structured JSON citing the exact source message ids, and malformed or provenance-free output is rejected; work is cached by source ids + content hashes; each block records provider/model/version/cost in metadata_json; per-channel and per-pod daily call caps are enforced (usage tracked in a new llm_usage table) with deterministic-only fallback when disabled, over budget, or failing. Editing/deleting/forgetting a covered source dirties the rollup through shared provenance so stale summaries stop serving. The worker is disabled unless CHANNEL_MEMORY_LLM_ENABLED=true and an OpenAI-compatible CHANNEL_MEMORY_LLM_BASE_URL are configured. Tests cover verbose->sparse compression with faithful hard events, queue ordering, malformed/provenance-free rejection, cache reuse by content hash, per-pod cost-cap enforcement, deterministic fallback when disabled/failing, and edit/forget provenance invalidation (synthetic source events). Closes #268 Refs #262
|
Codex independent review of PR #272 at Findings:
Focused local review note: the active workspace owner has unpushed in-progress fixes for both issues, but the PR head is still |
|
Independent review found two blockers in the initial async worker slice: rollup invalidation could suppress deterministic raw fallback for still-current messages, and the worker claimed cost caps while enforcing only call caps. Pushed a follow-up fix in a338f8f. Fixes included:
Validation:
No remaining blockers from my review. |
|
Codex re-review after hardening commit The two findings in my earlier review comment are addressed. The merged code now keeps deterministic raw blocks available as fallback while preferring fresh sparse rollups at serve time, restores fallback coverage when rollups are dirtied, validates full-window provenance, counts attempted calls against caps, and adds per-channel/per-pod USD budget knobs/enforcement. Verification I ran locally on the pushed head before merge:
No remaining blockers from my review. |
Summary
Adds the async, off-hot-path LLM digest worker to the channel-memory adapter — the final slice of the issue #232 Phase 2 / PR #262 design. It compresses verbose
raw_excerptwindows into sparsetopic_rollup/sequence_rollupblocks via an LLM, while/digeststays strictly LLM-free (reads already-generated blocks only).Conservative by design:
raw_excerptwindows are summarized; hard events, tombstones, telemetry keep their faithful deterministic blocksmetadata_jsonllm_usagetable); deterministic-only fallback when disabled, over budget, or failingCHANNEL_MEMORY_LLM_ENABLED=true+ an OpenAI-compatibleCHANNEL_MEMORY_LLM_BASE_URLare setAcceptance coverage (tests)
/digesthot pathValidation
go build ./...,go vet ./...cleango test ./examples/channel-memory/(worker + existing channel-memory: add SQLite source-message adapter #265 adapter tests) passgit diff --checkclean; no release pin / changelog / nav changesCloses #268
Refs #262